var SerialPort = require('serialport'); 
var EventEmitter = require('events').EventEmitter;   

var state = {};
var cmdarray = new Array();
var length =0;
var statechange = new EventEmitter();

const bytesToInt= (b)=>
{
    value = (((b[0] & 0xFF) << 24)
        | ((b[0 + 1] & 0xFF) << 16)
        | ((b[0 + 2] & 0xFF) << 8)
        | (b[0 + 3] & 0xFF));
    return value;
}

const add_crc = (data)  =>{
    var crc  =  0;
    for(var i = 0;i < data.length; i++){
        crc += data[i];
    }
    data[data.length] = crc;
    return data;
}

const crc_check = (arr)=> {
    let crc = 0;
    for (let i = 0; i < arr.length-1; i++) {
        crc += arr[i];
    }
    if(crc == arr[arr.length-1]) return true;
    return false;
}

const verify =(data) =>{
    console.log('verify: ' + data);
    var crc = crc_check(data);
    if(crc){
        state[data[1].toString()] = bytesToInt(data.slice(3,7));
        statechange.emit('changed', bytesToInt(data.slice(3,7)));
    }
    return crc;
}

const consume =() =>{
    var i=0;
    while(cmdarray.length>0){
        if(cmdarray[0] == 0x22){
            if(cmdarray.length>7){
                if(verify(cmdarray.slice(0,8))){
                    cmdarray.splice(0,8);
                    return i+8;
                }
            }else{
                return i;
            }
        }
        cmdarray.shift();
        i++;
    }
    return i;
}

const recvData = (data) =>{
    for(var i = 0;i < data.length;i++){
        cmdarray[length+i] = data[i];
    }
    length += data.length;
    while(cmdarray.length>7){
        length -= consume();
    }
}

const writePort = (port,data) => {
    port.write(data, function (err) {
        if (err) {
            return this.log('Error on write: ', err.message);
        }
        console.log('send: ' + data);
    });
}
function plc(com, baudrate,log){
    this.log=log;
    var port = new SerialPort(com, {
        baudRate: baudrate
    });
    port.on('data', recvData);

    this.setOn = function (address,channel,callback) {
        var data=new Array();
        data[0] = 0x55;
        data[1] = address;
        data[2] = 0x12;
        data[3] = 0x00;
        data[4] = 0x00;
        data[5] = 0x00;
        data[6] = channel;
        writePort(port,add_crc(data));
        callback(null);
    };

    this.setOff = function (address,channel,callback) {
        var data=new Array();
        data[0] = 0x55;
        data[1] = address;
        data[2] = 0x11;
        data[3] = 0x00;
        data[4] = 0x00;
        data[5] = 0x00;
        data[6] = channel;
        writePort(port,add_crc(data));
        callback(null);
    };

    this.getState = function (address,channel,callback) {
        callback(null,(state[address.toString()] >>> (channel-1)) & 1) ;
    };
}
module.exports = plc;
